/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package com.fzhucc.modules.thinktank.service;

import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.expert.domain.Expert;
import com.fzhucc.modules.pms.domain.Project;
import com.fzhucc.modules.pms.domain.ProjectScore;
import com.fzhucc.modules.pms.domain.dto.ProjectDto;
import com.fzhucc.modules.pms.domain.dto.ProjectExpertScoreDto;
import com.fzhucc.modules.pms.repository.ProjectRepository;
import com.fzhucc.modules.pms.service.ProjectService;
import com.fzhucc.modules.technical.domain.TechnicalProjectLog;
import com.fzhucc.modules.technical.domain.dto.TechnicalProjectDistributionDto;
import com.fzhucc.modules.thinktank.domain.Academician;
import com.fzhucc.modules.thinktank.domain.AcademicianProjectLog;
import com.fzhucc.modules.thinktank.domain.dto.AcademicianProjectDistributionDto;
import com.fzhucc.modules.thinktank.repository.AcademicianRepository;
import com.fzhucc.utils.*;
import lombok.RequiredArgsConstructor;
import com.fzhucc.modules.thinktank.repository.AcademicianProjectLogRepository;
import com.fzhucc.modules.thinktank.domain.dto.AcademicianProjectLogDto;
import com.fzhucc.modules.thinktank.domain.dto.AcademicianProjectLogQueryCriteria;
import com.fzhucc.modules.thinktank.service.mapstruct.AcademicianProjectLogMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author yyg
* @date 2023-01-03
**/
@Service
@RequiredArgsConstructor
public class AcademicianProjectLogService {

    private final AcademicianProjectLogRepository academicianProjectLogRepository;
    private final AcademicianProjectLogMapper academicianProjectLogMapper;

    private final AcademicianRepository academicianRepository;

    private final ProjectService projectService;

    private final ProjectRepository projectRepository;

    public Map<String,Object> queryAll(AcademicianProjectLogQueryCriteria criteria, Pageable pageable){
        Page<AcademicianProjectLog> page = academicianProjectLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(academicianProjectLogMapper::toDto));
    }

    public List<AcademicianProjectLogDto> queryAll(AcademicianProjectLogQueryCriteria criteria){
        return academicianProjectLogMapper.toDto(academicianProjectLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    public AcademicianProjectLogDto findById(Integer id) {
        AcademicianProjectLog academicianProjectLog = academicianProjectLogRepository.findById(id).orElseGet(AcademicianProjectLog::new);
        ValidationUtil.isNull(academicianProjectLog.getId(),"AcademicianProjectLog","id",id);
        return academicianProjectLogMapper.toDto(academicianProjectLog);
    }

    @Transactional(rollbackFor = Exception.class)
    public AcademicianProjectLogDto create(AcademicianProjectLog resources) {
        return academicianProjectLogMapper.toDto(academicianProjectLogRepository.save(resources));
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(AcademicianProjectLog resources) {
        AcademicianProjectLog academicianProjectLog = academicianProjectLogRepository.findById(resources.getId()).orElseGet(AcademicianProjectLog::new);
        ValidationUtil.isNull( academicianProjectLog.getId(),"AcademicianProjectLog","id",resources.getId());
        academicianProjectLog.copy(resources);
        academicianProjectLogRepository.save(academicianProjectLog);
    }

    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            academicianProjectLogRepository.deleteById(id);
        }
    }

    public void download(List<AcademicianProjectLogDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (AcademicianProjectLogDto academicianProjectLog : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("分配时间", academicianProjectLog.getRelationTime());
            map.put("院士id", academicianProjectLog.getAcademicianId());
            map.put("项目id", academicianProjectLog.getProjectId());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    public List<Long> getDifferenceSet(List<Long> allList, List<Long> list) {
        List<Long> resultList = new ArrayList<>();
        Map<String, Long> map = new HashMap<>();
        list.forEach(i2 -> {
            map.put(i2 + "", i2);
        });
        allList.forEach(i1 -> {
            Long m = map.get(i1 + "");
            //如果为空，则证明list2中无该数据
            if (m == null) {
                resultList.add(i1);
            }
        });
        return resultList;
    }

    @Transactional
    public void dodistribution(AcademicianProjectDistributionDto academicianProjectDistributionDto) {
        String project_id = academicianProjectDistributionDto.getProjectId();
        List<Long> list = academicianProjectDistributionDto.getListAcademicianId();
        List<Long> repeatlist = new ArrayList<Long>();
        Optional<Project> optionalProject = projectRepository.findById(project_id);
        if (optionalProject.isEmpty()) {
            throw new BadRequestException("项目未找到");
        }
        if (list == null) {
            throw new BadRequestException("院士之家id list未找到");
        }
        //先删除所有该项目的绑定的院士之家
        List<AcademicianProjectLog> listAcademicianProjectLog = academicianProjectLogRepository.findByProjectId(project_id);
        for (AcademicianProjectLog academicianProjectLog : listAcademicianProjectLog) {
            Long academicianId = academicianProjectLog.getAcademicianId();
            if (list.indexOf(academicianId) == -1) { //不在则删除
                academicianProjectLogRepository.deleteById(academicianProjectLog.getId());
            } else {
                repeatlist.add(academicianId);
            }
        }
        list = getDifferenceSet(list, repeatlist);
        for (Long ids : list) {
            //在新增新的院士之家
            AcademicianProjectLog academicianProjectLog = new AcademicianProjectLog();
            academicianProjectLog.setProjectId(project_id);
            academicianProjectLog.setAcademicianId(ids);
            academicianProjectLog.setRelationTime(new Timestamp(new Date().getTime()));
            academicianProjectLog.setProjectLevel(optionalProject.get().getLevel());
            academicianProjectLogRepository.save(academicianProjectLog);
        }
    }

    public Map<String, Object> getAcademicianProjectByLoginUser(Pageable pageable) {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        Page<Project> page = projectRepository.findAllByAcademicianUser(userId, pageable);
        return PageUtil.toPage(page);
    }

    public List<Academician> getAcademicianByProjectId(String projectId) {
        List<Academician> academician_list = new ArrayList<Academician>();
        List<AcademicianProjectLog> list = academicianProjectLogRepository.findByProjectId(projectId);
        if (list == null) {
            throw new BadRequestException("智库院士之家评分表项目未找到");
        }
        for (int i = 0; i < list.size(); i++) {
            AcademicianProjectLog academicianProjectLog = list.get(i);
            Long academicianId = academicianProjectLog.getAcademicianId();
            Optional<Academician> res = academicianRepository.findById(academicianId);
            if (res.isPresent()){
                academician_list.add(res.get());
            }
        }
        return academician_list;
    }

    public Map<String, Object> getProjectByLoginUser(Pageable pageable) {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        Page<Project> page = projectRepository.findAllByAcademicianUser(userId, pageable);
        return PageUtil.toPage(page);
    }

    public void expertRating(ProjectExpertScoreDto projectExpertScoreDto) {
        BigDecimal score = projectExpertScoreDto.getScore();
        String projectId = projectExpertScoreDto.getProjectId();
        if (score == null) {
            throw new BadRequestException("评分为null");
        }
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        Optional<Project> optionalProject = projectRepository.findById(projectId);
        if (optionalProject.isEmpty()) {
            throw new BadRequestException("项目未找到");
        }
        Academician academician = academicianRepository.findByUserId(userId);
        if (academician == null) {
            throw new BadRequestException("未找到院士之家专家");
        }
        Long expertId = academician.getId();
        //专家评分只能查找当前阶段level进行评分
        List<AcademicianProjectLog> list = academicianProjectLogRepository.findByExpertIdAndProjectIdWithLevel(expertId, projectId, optionalProject.get().getLevel());
        if (list == null || list.size() != 1) {
            throw new BadRequestException("院士之家专家未分配指定项目");
        }
        AcademicianProjectLog academicianProjectLog = list.get(0);
        academicianProjectLog.setScore(score);
        academicianProjectLog.setScoreTime(new Date());
        academicianProjectLog.setAdvice(projectExpertScoreDto.getAdvice());
        academicianProjectLogRepository.save(academicianProjectLog);
    }

    public ProjectDto getProjectScoreByProjectId(String projectId) {
        ProjectDto projectDto = projectService.findById(projectId);
        if (projectDto == null) {
            throw new BadRequestException("项目未找到");
        }
        List<AcademicianProjectLog> list = academicianProjectLogRepository.findByProjectId(projectId);
        projectDto.setAcademicianScoreSituation(list);
        return projectDto;
    }

    public ProjectDto getProjectScoreByProjectIdSiftLevel(String projectId) {
        ProjectDto projectDto = projectService.findById(projectId);
        if (projectDto == null) {
            throw new BadRequestException("项目未找到");
        }
        List<AcademicianProjectLog> list1 = academicianProjectLogRepository.findByProjectIdProjectLevel(projectId, 1);
        projectDto.setListAcademicianLevel1(list1);
        List<AcademicianProjectLog> list2 = academicianProjectLogRepository.findByProjectIdProjectLevel(projectId, 2);
        projectDto.setListAcademicianLevel2(list2);
        List<AcademicianProjectLog> list3 = academicianProjectLogRepository.findByProjectIdProjectLevel(projectId, 3);
        projectDto.setListAcademicianLevel3(list3);
        return projectDto;
    }

    public boolean getIsScoreByProjectId(String projectId) {
        Optional<Project> optionalProject = projectRepository.findById(projectId);
        if (optionalProject.isEmpty()) {
            throw new BadRequestException("项目未找到");
        }
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("登录用户ID未找到");
        }
        Academician expert = academicianRepository.findByUserId(userId);
        if (expert == null) {
            throw new BadRequestException("院士之家专家未找到");
        }
        List<AcademicianProjectLog> list = academicianProjectLogRepository.findByExpertIdAndProjectIdWithLevel(expert.getId(), projectId, optionalProject.get().getLevel());
        if (list != null && list.size() == 1) {
            AcademicianProjectLog academicianProjectLog = list.get(0);
            if (academicianProjectLog != null) {
                BigDecimal score = academicianProjectLog.getScore();
                if (score != null) {
                    return true;
                }
            }
        }
        return false;
    }

    public ProjectDto getByProjectIdAndLoginUser(String projectId) {
        ProjectDto projectDto = projectService.findById(projectId);
        if (projectDto == null) {
            throw new BadRequestException("项目未找到");
        }
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("登录用户ID未找到");
        }
        Academician expert = academicianRepository.findByUserId(userId);
        if (expert == null) {
            throw new BadRequestException("院士之家专家未找到");
        }
        List<AcademicianProjectLog> list = academicianProjectLogRepository.findByExpertIdAndProjectId(expert.getId(), projectId);
        projectDto.setAcademicianScoreSituation(list);
        return projectDto;
    }

    public ProjectDto getByProjectIdAndLoginUserSiftLevel(String projectId) {
        ProjectDto projectDto = projectService.findById(projectId);
        if (projectDto == null) {
            throw new BadRequestException("项目未找到");
        }
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("登录用户ID未找到");
        }
        Academician expert = academicianRepository.findByUserId(userId);
        if (expert == null) {
            throw new BadRequestException("院士之家专家未找到");
        }
        List<AcademicianProjectLog> list1 = academicianProjectLogRepository.findByExpertIdAndProjectIdWithLevel(expert.getId(), projectId, 1);
        projectDto.setListAcademicianLevel1(list1);
        List<AcademicianProjectLog> list2 = academicianProjectLogRepository.findByExpertIdAndProjectIdWithLevel(expert.getId(), projectId, 2);
        projectDto.setListAcademicianLevel2(list2);
        List<AcademicianProjectLog> list3 = academicianProjectLogRepository.findByExpertIdAndProjectIdWithLevel(expert.getId(), projectId, 3);
        projectDto.setListAcademicianLevel3(list3);
        return projectDto;
    }
}